package com.taotaojs.mybootsuper.service;

import com.taotaojs.mybootsuper.ConfigConstant;
import com.taotaojs.mybootsuper.bean.BaseBean;
import com.taotaojs.mybootsuper.mapper.MyComMapper;
import com.taotaojs.mybootsuper.mapper.MySqlBuild;
import com.taotaojs.util.CollectionUtil;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

/**
 * 通用Service的批量操作方法类
 * @author: TaoTaojs
 * @Date: 2020年03月20日15:49:46
 * @Description:
 * 批量操作方法
 * @关联类:
 * @参考链接：
 */
public class MyBatchService<T extends BaseBean> {

    public final Class<T> clazz;

    MyBatchService(){
        ParameterizedType type = (ParameterizedType) this.getClass()
                .getGenericSuperclass();
        this.clazz = (Class<T>) type.getActualTypeArguments()[0];
    }

    @Autowired
    protected MyComMapper<T> myMapper;
    /**
     * 批量插入方法
     * @param list
     * @return
     */
    public Integer batchInsertObject(List<T> list) {
        return batchProcessingHub(list, null, 1);
    }
    public Integer batchInsertObject(List<T> list, MySqlBuild<T> sql) {
        return batchProcessingHub(list, sql, 1);
    }
    private Integer batchInsert(MySqlBuild<T> sql) {
        if(CollectionUtil.isEmpty(sql.getList())) {
            return 0;
        }
        return myMapper.insertObjList(sql);
    }


    /**
     * 批量删除方法
     * @param list
     * @return
     */
    public Integer batchDeleteObject(List<T> list) {
        return batchProcessingHub(list, null, -1);
    }
    public Integer batchDeleteObject(List<T> list, MySqlBuild<T> sql) {
        return batchProcessingHub(list, sql, -1);
    }
    private Integer batchDelete(MySqlBuild<T> sql) {
        if(CollectionUtil.isEmpty(sql.getList())) {
            return 0;
        }

        List<Integer> ids = new ArrayList<>();
        for (T t : sql.getList()) {
            ids.add(t.getId());
        }
        sql.setList(null);
        sql.setDeleteList(ids);

        return myMapper.deleteObjList(sql);
    }

    /**
     * 批量更新方法
     * @param list
     * @return
     */
    public Integer batchUpdateObject(List<T> list) {
        return batchProcessingHub(list, null, 0);
    }
    public Integer batchUpdateObject(List<T> list, MySqlBuild<T> sql) {
        return batchProcessingHub(list, sql, 0);
    }
    private Integer batchUpdate(MySqlBuild<T> sql) {
        if(CollectionUtil.isEmpty(sql.getList())) {
            return 0;
        }
        return myMapper.updateObjList(sql);
    }

    /**
     * 批量假删除
     * @param list
     * @return
     */
    public Integer batchUpdateByDeleteObject(List<T> list) {
        return batchUpdateByDeleteObject(list, null);
    }
    public Integer batchUpdateByDeleteObject(List<T> list, MySqlBuild<T> sql) {
        for (T t : list) {
            t.setEnabled(false);
        }
        return batchProcessingHub(list, sql, 0);
    }

    /**
     * 全部执行批量操作
     * @param list
     * @param listVO
     * @param listDb
     * @throws RuntimeException
     */
    public void batchAll(List<T> list, List<T> listVO, List<T> listDb) {
        if(!CollectionUtil.isEmpty(list)) {
            this.batchUpdateObject(list);
        }

        if(!CollectionUtil.isEmpty(listVO)) {
            this.batchInsertObject(listVO);
        }

        if(!CollectionUtil.isEmpty(listDb)) {
            this.batchDeleteObject(listDb);
        }

    }

    /**
     * 分批次处理中枢
     * @param list
     * @param sql
     * @param type 1=insert  0=update  -1delete
     */
    private int batchProcessingHub(List<T> list, MySqlBuild<T> sql, int type){
        if(sql == null) {
            sql = new MySqlBuild<>();
        }

        //分批次处理
        //当前次数
        int index = 1;
        //成功处理的数据条数
        int success = 0;
        do {
            if(list.size() < index * ConfigConstant.BATCH_COUNT){
                //当剩余总量小于批次量的时候
                sql.setList(list.subList((index-1) * ConfigConstant.BATCH_COUNT, list.size()));
            } else {
                sql.setList(list.subList((index-1) * ConfigConstant.BATCH_COUNT, index * ConfigConstant.BATCH_COUNT));
            }
            if(type == 1){
                success += batchInsert(sql);
            } else if(type == 0) {
                success += batchUpdate(sql);
            } else if(type == -1) {
                success += batchDelete(sql);
            }
        }while (index++ * ConfigConstant.BATCH_COUNT < list.size());
        return success;
    }

}
